using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;

namespace ECLiPSe.Net
{
    public class EclipseStreams
    {
        #region Properties

        private const int ExdrVersion = 1;
        
        private void SetVarMode(EclipseStreamMode varMode)
        {
            _varMode = varMode;
        }
        private EclipseStreamMode _varMode;

        internal void SetVarStreamId(long varStreamId)
        {
            _varStreamId = varStreamId;
        }
        private long _varStreamId;

        internal void SetPrompt(string prompt)
        {
            _prompt = prompt;
        }
        private string _prompt;
        
        internal void SetKey(string key)
        {
            _key = key;
        }
        private string _key;

        #endregion

        #region ECLiPSe Imports

        /// <summary>
        /// Ec_queue_writes the specified stream nr.
        /// </summary>
        /// <param name="StreamNr">The stream nr.</param>
        /// <param name="buffer">The buffer.</param>
        /// <param name="length">The length.</param>
        /// <returns></returns>
        [DllImport("eclipse.dll")]
        private static extern long ec_queue_write(
            long StreamNr
            , string buffer
            , long length);

        /// <summary>
        /// Ec_queue_reads the specified stream nr.
        /// </summary>
        /// <param name="StreamNr">The stream nr.</param>
        /// <param name="buffer">The buffer.</param>
        /// <param name="length">The length.</param>
        /// <returns></returns>
        [DllImport("eclipse.dll")]
        private static extern long ec_queue_read(
            long StreamNr
            , string buffer
            , long length);

        /// <summary>
        /// Ec_int32_xdrs the specified l.
        /// </summary>
        /// <param name="l">The l.</param>
        /// <param name="xdrString">The XDR string.</param>
        [DllImport("eclipse.dll")]
        private static extern void ec_int32_xdr(
            long l
            , string xdrString);

        /// <summary>
        /// Ec_double_xdrs the specified d.
        /// </summary>
        /// <param name="d">The d.</param>
        /// <param name="xdrString">The XDR string.</param>
        [DllImport("eclipse.dll")]
        private static extern void ec_double_xdr(
            double d
            , string xdrString);

        /// <summary>
        /// Ec_xdr_int32s the specified XDR string.
        /// </summary>
        /// <param name="xdrString">The XDR string.</param>
        /// <param name="l">The l.</param>
        [DllImport("eclipse.dll")]
        private static extern void ec_xdr_int32(
            string xdrString
            , long l);

        /// <summary>
        /// Ec_xdr_doubles the specified XDR string.
        /// </summary>
        /// <param name="xdrString">The XDR string.</param>
        /// <param name="d">The d.</param>
        [DllImport("eclipse.dll")]
        private static extern void ec_xdr_double(
            string xdrString
            , double d);

        #endregion

        #region Methods

        /// <summary>
        /// Writes to the Eclipse Stream.
        /// </summary>
        /// <param name="Data">The data.</param>
        public void StreamWrite(string Data)
        {
            if(_varMode == EclipseStreamMode.FromEclipse)
            {
                throw new Exception(
                    string.Format("{1}::StreamWrite{0}Writing to a FromEclipse Stream{0}{2}"
                                  , Environment.NewLine
                                  , Assembly.GetCallingAssembly().GetType()
                                  , _key)
                    );
            }

            ec_queue_write(_varStreamId, Data, Data.Length);

        }

        /// <summary>
        /// Reads the stream output.
        /// </summary>
        /// <param name="l">The l.</param>
        /// <returns></returns>
        public string Read(long l)
        {

            if (_varMode == EclipseStreamMode.ToEclipse)
            {
                throw new Exception(
                    string.Format("{1}::StreamWrite{0}Reading from a ToEclipse Stream{0}{2}"
                                  , Environment.NewLine
                                  , Assembly.GetCallingAssembly().GetType()
                                  , _key)
                    );
            }


            string buffer = new string(' ', (int)l);
            long ret = ec_queue_read(_varStreamId, buffer, l);

            if(ret < 1)
            {
                buffer = buffer.Substring((int)l);
            }

            return buffer;
        }

        public string NewData()
        {
            string newData;
            string buffer = new string(' ', 1000);
            long lenbuf = ec_queue_read(_varStreamId, buffer, 1000);
            if(lenbuf == 1000)
            {
                newData = buffer + NewData();
            }
            else if(lenbuf == -192)
            {
                throw new Exception(
                    string.Format("{1}::StreamWrite{0}Trying to read from a stream that is not a queue{0}{2}"
                                  , Environment.NewLine
                                  , Assembly.GetCallingAssembly().GetType()
                                  , _key)
                    );
            }
            else
            {
                newData = buffer.Substring(0, (int) lenbuf);
            }

            return newData;
            
        }

        public void WriteExdr(object Data)
        {
            
        }

        private string Exdr(object Data)
        {
            string o = string.Empty;
            string buff;
            long i;

            return o;
        }

        /// <summary>
        /// Flushes this instance.
        /// </summary>
        public void Flush()
        {
            if(_varMode ==EclipseStreamMode.ToEclipse)
            {
                FlushStream(this,null);
            }
        }
        #endregion

        #region Events

        /// <summary>
        /// Internal Event Handler
        /// </summary>
        protected internal delegate void CustomEventHandler(object sender, EventArgs e);

        private event CustomEventHandler FlushStream;

        #endregion



        #region Enums

        enum EclipseStreamMode
        {
            ToEclipse
            , FromEclipse
        }

        #endregion
    }
}